package cn.elwy.rcp.ui.dialog;

import java.util.HashMap;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import cn.elwy.common.exception.MsgLevel;
import cn.elwy.common.util.AssertUtil;
import cn.elwy.rcp.core.model.ui.entity.MsgInfo;
import cn.elwy.rcp.ui.Msg;
import cn.elwy.rcp.ui.handler.AutoCloseShell;

public class CMsgDialog extends CDialog {

  public static final HashMap<MsgLevel, Image> titleImageMap = new HashMap<MsgLevel, Image>();
  public static final HashMap<MsgLevel, Image> labelImageMap = new HashMap<MsgLevel, Image>();

  private int minimumWidth = 270;
  private int minimumHeight = 170;

  private MsgInfo msgInfo;
  private Text messageLabel;
  private Control dialogArea;
  private Label messageImageLabel;

  private Text detailText;
  private Button detailsButton;
  private Composite detailArea;
  private int heightHint = 80;
  private int detailHeightHint = 300;
  private String detailMessage;
  private boolean resize;

  static {
    titleImageMap.put(MsgLevel.INFO, JFaceResources.getImage(DLG_IMG_MESSAGE_INFO));
    titleImageMap.put(MsgLevel.ERROR, JFaceResources.getImage(DLG_IMG_MESSAGE_ERROR));
    titleImageMap.put(MsgLevel.WARN, JFaceResources.getImage(DLG_IMG_MESSAGE_WARNING));

    labelImageMap.put(MsgLevel.INFO, Display.getDefault().getSystemImage(SWT.ICON_INFORMATION));
    labelImageMap.put(MsgLevel.ERROR, Display.getDefault().getSystemImage(SWT.ICON_ERROR));
    labelImageMap.put(MsgLevel.QUESTION, Display.getDefault().getSystemImage(SWT.ICON_QUESTION));
    labelImageMap.put(MsgLevel.WARN, Display.getDefault().getSystemImage(SWT.ICON_WARNING));
  }

  /**
   * @wbp.parser.constructor
   */
  public CMsgDialog(Shell parentShell, MsgInfo msgInfo) {
    super(parentShell);
    Assert.isNotNull(msgInfo, "");
    this.msgInfo = msgInfo;
    init(msgInfo);
  }

  /**
   * @wbp.parser.constructor
   */
  public CMsgDialog(Shell parentShell, int style, MsgInfo msgInfo) {
    super(parentShell, style);
    Assert.isNotNull(msgInfo, "");
    this.msgInfo = msgInfo;
    init(msgInfo);
  }

  private void init(MsgInfo msgInfo) {
    detailMessage = msgInfo.getDetailMessage();
    if (AssertUtil.isNotEmpty(detailMessage)) {
      resize = true;
      setShellStyle(getShellStyle() | SWT.MAX | SWT.RESIZE);
      minimumWidth = 600;
    }
  }

  protected Control createContents(Composite parent) {
    if (msgInfo.isAutoClose()) {
      AutoCloseShell au = new AutoCloseShell(getShell(), 3);
      au.start();
    }
    getShell().setMinimumSize(minimumWidth, minimumHeight);
    return super.createContents(parent);
  }

  protected Composite createDialogArea(Composite parent) {
    Composite dialogArea = new Composite(parent, SWT.NONE);

    GridData gd_dialogArea = new GridData(GridData.FILL_BOTH);
    gd_dialogArea.heightHint = heightHint;
    gd_dialogArea.minimumHeight = heightHint;
    gd_dialogArea.widthHint = minimumWidth - 10;
    gd_dialogArea.minimumWidth = minimumWidth - 10;

    if ((~getShellStyle() & SWT.RESIZE) == 0) {
      gd_dialogArea.grabExcessVerticalSpace = false;
    }
    dialogArea.setLayoutData(gd_dialogArea);
    GridLayout gl_dialogArea = new GridLayout(2, false);
    gl_dialogArea.marginWidth = 10;
    gl_dialogArea.marginHeight = 10;
    gl_dialogArea.verticalSpacing = 10;
    gl_dialogArea.horizontalSpacing = 10;
    dialogArea.setLayout(gl_dialogArea);

    applyDialogFont(dialogArea);

    messageImageLabel = new Label(dialogArea, SWT.CENTER);
    messageImageLabel.setImage(getLabelImage());

    messageLabel = new Text(dialogArea, SWT.READ_ONLY | SWT.WRAP);
    GridData gd_messageLabel = new GridData(GridData.FILL_BOTH);
    gd_messageLabel.verticalAlignment = SWT.CENTER;
    messageLabel.setLayoutData(gd_messageLabel);
    String message = msgInfo.getMessage();
    if (AssertUtil.isNotEmpty(message)) {
      messageLabel.setText(message);
    }
    messageLabel.setFont(JFaceResources.getDialogFont());

    dialogArea.setFont(JFaceResources.getDialogFont());
    initializeDialogUnits(dialogArea);
    return dialogArea;
  }

  protected Composite createDetailArea(Composite parent) {
    Composite bodyArea = new Composite(parent, SWT.NONE);
    bodyArea.setLayout(new GridLayout(1, false));
    GridData layoutData = new GridData(GridData.FILL_BOTH);
    bodyArea.setLayoutData(layoutData);
    layoutData.widthHint = minimumWidth - 10;
    layoutData.minimumWidth = minimumWidth - 10;
    layoutData.heightHint = detailHeightHint;
    layoutData.minimumHeight = detailHeightHint;
    bodyArea.setLayoutData(layoutData);

    applyDialogFont(bodyArea);

    detailText = new Text(bodyArea, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | SWT.V_SCROLL);
    if (AssertUtil.isNotEmpty(detailMessage)) {
      detailText.setText(detailMessage);
    }

    detailText.setFont(JFaceResources.getDialogFont());
    GridData gd_detailText = new GridData(GridData.FILL_BOTH);
    detailText.setLayoutData(gd_detailText);
    return bodyArea;
  }

  protected void createButtonsForButtonBar(Composite parent) {
    String[] buttonLabels = getButtonLabels(msgInfo.getMsgLevel());
    for (int i = 0; i < buttonLabels.length; i++) {
      String label = buttonLabels[i];
      createButton(parent, i, label, i == 0);
    }

    if (AssertUtil.isNotEmpty(detailMessage)) {
      detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL, false);
    }
  }

  /**
   * @param kind
   * @return
   */
  String[] getButtonLabels(String msgLevel) {
    String[] dialogButtonLabels;
    MsgLevel enumType = MsgLevel.getEnumType(msgLevel);
    switch (enumType) {
      case INFO:
      case ERROR:
      case WARN: {
        dialogButtonLabels = new String[] { IDialogConstants.OK_LABEL };
        break;
      }
      case CONFIRM: {
        dialogButtonLabels = new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL };
        break;
      }
      case QUESTION: {
        dialogButtonLabels = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL };
        break;
      }
      case QUESTION_WITH_CANCEL: {
        dialogButtonLabels = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL,
            IDialogConstants.CANCEL_LABEL };
        break;
      }
      default: {
        throw new IllegalArgumentException("Illegal value for kind in MessageDialog.open()"); //$NON-NLS-1$
      }
    }
    return dialogButtonLabels;
  }

  @Override
  protected void buttonPressed(int buttonId, SelectionEvent event) {
    if (IDialogConstants.DETAILS_ID == buttonId) {
      detailPressed(event);
    } else {
      setReturnCode(buttonId);
      close();
    }
  }

  protected boolean detailPressed(SelectionEvent event) {
    // Point windowSize = getShell().getSize();
    // Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
    if (detailArea != null && !detailArea.isDisposed()) {
      detailArea.dispose();
      detailArea = null;
      detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
    } else {
      detailArea = createDetailArea((Composite) getContents());
      detailText.setFocus();
      detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
    }
    // Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
    // getShell().setSize(windowSize.x, windowSize.y + (newSize.y - oldSize.y));
    getShell().pack();
    return true;
  }

  public Image getTitleImage() {
    if (!msgInfo.isCustomTitleImage()) {
      return null;
    }

    Image image = titleImageMap.get(msgInfo.getMsgLevel());
    if (image == null) {
      return titleImageMap.get(MsgLevel.INFO);
    }
    return image;
  }

  public Image getLabelImage() {
    Image image = labelImageMap.get(msgInfo.getMsgLevel());
    if (image == null) {
      return labelImageMap.get(MsgLevel.INFO);
    }
    return image;
  }

  public String getTitle() {
    String title = msgInfo.getTitle();
    if (title != null && !title.isEmpty()) {
      return title;
    }
    MsgLevel enumType = MsgLevel.getEnumType(msgInfo.getMsgLevel());
    switch (enumType) {
      case ERROR:
        return Msg.getString("m_error"); //$NON-NLS-1$
      case INFO:
        return Msg.getString("m_information"); //$NON-NLS-1$
      case QUESTION:
        return Msg.getString("m_question"); //$NON-NLS-1$
      case WARN:
        return Msg.getString("m_warning"); //$NON-NLS-1$
      case NONE:
      default:
        return ""; //$NON-NLS-1$
    }
  }

  public Text getMessageLabel() {
    return messageLabel;
  }

  public void setMessageLabel(Text messageLabel) {
    this.messageLabel = messageLabel;
  }

  public Control getDialogArea() {
    return dialogArea;
  }

  public void setDialogArea(Control dialogArea) {
    this.dialogArea = dialogArea;
  }

  public Label getMessageImageLabel() {
    return messageImageLabel;
  }

  public void setMessageImageLabel(Label messageImageLabel) {
    this.messageImageLabel = messageImageLabel;
  }

  /** 设置窗口居中 */
  @Override
  protected Point getInitialLocation(Point initialSize) {
    Rectangle shellBounds = null;
    if (getParentShell() == null) {
      shellBounds = Display.getCurrent().getBounds();
    } else {
      shellBounds = getParentShell().getBounds();
    }
    Point dialogSize = initialSize;
    int y = shellBounds.height - dialogSize.y;
    if (resize) {
      y = y - detailHeightHint;
    }
    return new Point(shellBounds.x + (shellBounds.width - dialogSize.x) / 2, shellBounds.y + y / 2);
  }

  @Override
  protected void configureShell(Shell newShell) {
    super.configureShell(newShell);
    Image titleImage = getTitleImage();
    if (titleImage != null) {
      newShell.setImage(titleImage);
    }
    newShell.setText(getTitle());
  }

}
